package com.spring.boot.demo.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.spring.boot.demo.pojo.User;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Map;

/**
 * @author ZhuYouBin
 * @version 1.0.0
 * @Date: 2022/11/21 22:45
 * @Description ES数据操作
 */
@RestController
@RequestMapping("/api/es/doc")
public class DocController {

    private static int seqNo = 1;

    @Autowired
    private RestHighLevelClient highRestClient;

    @PostMapping("/create")
    public String createDoc(@RequestBody Map<String, Object> map) throws IOException {
        // 创建索引请求: 指定操作doc数据保存到哪个索引下面，索引不存在，则会创建索引
        IndexRequest indexRequest = new IndexRequest("idx_20221122");
        // 指定doc文档的唯一id标识, 如果不指定，则ES会默认生成一个值
        indexRequest.id("2022112100" + (seqNo++));
        // 设置需要保存的数据，即：doc文档
        indexRequest.source(map);
        // 指定本次请求的操作类型，create 表示创建
        indexRequest.opType(DocWriteRequest.OpType.CREATE);
        // 执行请求
        IndexResponse response = highRestClient.index(indexRequest, RequestOptions.DEFAULT);
        // 处理响应结果
        DocWriteResponse.Result result = response.getResult();
        String lowercase = result.getLowercase();
        System.out.println("result: " + lowercase);
        return "success.";
    }

    @PostMapping("/update")
    public String updateDoc(@RequestBody Map<String, Object> map, @RequestParam("id") String id) throws IOException {
        // 创建更新doc文档的请求: 指定操作哪个索引下的doc文档
        UpdateRequest updateRequest = new UpdateRequest("idx_20221122", id);
        // 设置需要保存的数据，即：doc文档
        updateRequest.doc(map);
        // 执行更新请求
        UpdateResponse response = highRestClient.update(updateRequest, RequestOptions.DEFAULT);
        // 处理响应结果
        DocWriteResponse.Result result = response.getResult();
        String lowercase = result.getLowercase();
        System.out.println("result: " + lowercase);
        return "success.";
    }

    @GetMapping("/delete")
    public String deleteDoc(@RequestParam("id") String id) throws IOException {
        // 创建删除doc文档的请求: 指定删除哪个索引下的doc文档
        DeleteRequest deleteIndexRequest = new DeleteRequest("idx_20221122", id);
        // 执行删除请求
        DeleteResponse response = highRestClient.delete(deleteIndexRequest, RequestOptions.DEFAULT);
        // 处理响应结果
        DocWriteResponse.Result result = response.getResult();
        String lowercase = result.getLowercase();
        System.out.println("result: " + lowercase);
        return "success.";
    }

    @GetMapping("/get")
    public String getDoc(@RequestParam("id") String id) throws IOException {
        // 创建删除doc文档的请求: 指定查询哪个索引下的doc文档
        GetRequest getRequest = new GetRequest("idx_20221122", id);
        // 执行删除请求
        GetResponse response = highRestClient.get(getRequest, RequestOptions.DEFAULT);
        // 处理响应结果: 获取doc文档数据
        Map<String, Object> source = response.getSource();
        System.out.println(source);
        return "success.";
    }

    @GetMapping("/exists")
    public String existsDoc(@RequestParam("id") String id) throws IOException {
        // 创建删除doc文档的请求: 指定查询哪个索引下的doc文档
        GetRequest getRequest = new GetRequest("idx_20221122", id);
        // 因为这里只是判断doc文档存不存在，没必要查询具体的数据内容，所以可以指定不返回数据内容
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        // 执行删除请求
        boolean exists = highRestClient.exists(getRequest, RequestOptions.DEFAULT);
        // 处理响应结果
        System.out.println("doc文档是否存在: " + exists);
        return "success.";
    }

    @GetMapping("/bulk")
    public String bulkDoc() throws IOException {
        // 创建批量请求
        BulkRequest bulkRequest = new BulkRequest();
        // 模拟数据
        for (int i = 0; i < 10; i++) {
            IndexRequest indexRequest = new IndexRequest("idx_20221122");
            indexRequest.id("doc_id00" + i); // 设置doc文档的id
            User user = new User("test-name-00" + i, "abcd00100" + i, 20 + i);
            ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(user);
            indexRequest.source(json, XContentType.JSON);
            // 添加到bulk里面
            bulkRequest.add(indexRequest);
        }
        // 批量执行创建请求
        BulkResponse response = highRestClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        // 处理响应结果
        boolean hasFailures = response.hasFailures();
        if (hasFailures) {
            System.out.println("批量创建文档失败");
        }
        // 获取每一个请求响应
        BulkItemResponse[] responseItems = response.getItems();
        for (BulkItemResponse responseItem : responseItems) {
            int status = responseItem.status().getStatus();
            // bulk批量操作时候，第一次创建doc文档，返回的201状态码
            // 之后更新文档，是返回200状态码
            if (status != 200 && status != 201) {
                System.out.println("status=" + status + ",执行失败,id=" + responseItem.getId());
            } else {
                System.out.println("status=" + status + ",执行成功,id=" + responseItem.getId());
            }
        }
        return "success.";
    }

}
